using System;
using System.Windows.Forms;

namespace Pegasus.Windows.Forms.Explorer
{
	/// <summary>
	/// Implements a explore view (tree and list/view) 
	/// </summary>
	/// <remarks>This class is still under development.</remarks>
	public partial class ExplorerView : UserControl
	{
		// Local Instance Values
		private IExplorerTree m_explorerTree = null;
		private IExplorerList m_explorerList = null;
		private ExplorerNodeCollection m_childNodes = new ExplorerNodeCollection();

		private ImageList m_smallImageList = null;
		private ImageList m_largeImageList = null;

		/// <summary>
		/// Initializes a new instance of the <see cref="ExplorerView"/> class.
		/// </summary>
		public ExplorerView()
		{
			InitializeComponent();
			InitializeControl();

			m_childNodes.OnNodeAdded += new EventHandler<ExplorerEventArgs>( ChildNodes_OnNodeAdded );
			m_childNodes.OnNodeRemoved += new EventHandler<ExplorerEventArgs>( ChildNodes_OnNodeRemoved );
			m_childNodes.OnCollectionClearing += new EventHandler<EventArgs>( ChildNodes_OnCollectionClearing );
			m_childNodes.OnCollectionCleared += new EventHandler<EventArgs>( ChildNodes_OnCollectionCleared );
		}

		/// <summary>
		/// Gets or sets the view.
		/// </summary>
		/// <value>The view.</value>
		public View View
		{
			get
			{
				return m_explorerList.View;
			}

			set
			{
				m_explorerList.View = value;
			}
		}

		/// <summary>
		/// Gets or sets the selected node.
		/// </summary>
		/// <value>The selected node.</value>
		public ExplorerNode SelectedTreeNode
		{
			get
			{
				return m_explorerTree.SelectedTreeNode;
			}

			set
			{
				m_explorerTree.SelectedTreeNode = value;
			}
		}

		/// <summary>
		/// Gets or sets the list of selected nodes.
		/// </summary>
		/// <value>The list of selected nodes.</value>
		public ExplorerNode[] SelectedListNodes
		{
			get
			{
				return m_explorerList.SelectedListNodes;
			}

			set
			{
				m_explorerList.SelectedListNodes = value;
			}
		}

		/// <summary>
		/// Gets the nodes.
		/// </summary>
		/// <value>The nodes.</value>
		public ExplorerNodeCollection Nodes
		{
			get
			{
				return m_childNodes;
			}
		}

		/// <summary>
		/// Gets or sets the small image list.
		/// </summary>
		/// <value>The small image list.</value>
		public ImageList SmallImageList
		{
			get
			{
				return m_smallImageList;
			}

			set
			{
				m_smallImageList = value;
				m_explorerTree.SetImageList( m_smallImageList );
				m_explorerList.SetImageList( m_smallImageList, m_largeImageList );
			}
		}

		/// <summary>
		/// Gets or sets the large image list.
		/// </summary>
		/// <value>The large image list.</value>
		public ImageList LargeImageList
		{
			get
			{
				return m_largeImageList;
			}
		
			set
			{
				m_largeImageList = value;
				m_explorerList.SetImageList( m_smallImageList, m_largeImageList );
			}
		}

		/// <summary>
		/// Forces the control to invalidate its client area and immediately redraw itself and any child controls.
		/// </summary>
		/// <PermissionSet><IPermission class="System.Security.Permissions.EnvironmentPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true"/><IPermission class="System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true"/><IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="UnmanagedCode, ControlEvidence"/><IPermission class="System.Diagnostics.PerformanceCounterPermission, System, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true"/></PermissionSet>
		public override void Refresh()
		{
			// Save the currently selected item in the tree.
			string selectedTreePath = null;
			ExplorerNode treeNode = SelectedTreeNode;
			if( treeNode != null )
			{
				selectedTreePath = treeNode.Path;
				SelectedTreeNode = null;
			}

			// Refresh all the root nodes.
			foreach( ExplorerNode node in Nodes )
			{
				node.RefreshNode();
			}

			// If we had a selected node then reselect it.
			if( !string.IsNullOrEmpty( selectedTreePath ) )
			{
				treeNode = GetNodeByPath( selectedTreePath );
				if( treeNode != null )
				{
					SelectedTreeNode = treeNode;
				}
			}

			base.Refresh();
		}

		/// <summary>
		/// Gets the node by key.
		/// </summary>
		/// <param name="key">The key.</param>
		/// <returns>The explorer node or null if the node is not found.</returns>
		public ExplorerNode GetNodeByKey( string key )
		{
			return m_explorerTree.GetNodeByKey( key );
		}

		/// <summary>
		/// Gets the node by path.
		/// </summary>
		/// <param name="path">The path.</param>
		/// <returns>The explorer node or null if the node is not found.</returns>
		public ExplorerNode GetNodeByPath( string path )
		{
			return m_explorerTree.GetNodeByPath( path );
		}

		/// <summary>
		/// Adds the node.
		/// </summary>
		/// <param name="node">The node.</param>
		internal virtual void AddNode( ExplorerNode node )
		{
			m_explorerTree.AddNode( node );
		}

		/// <summary>
		/// Removes the node.
		/// </summary>
		/// <param name="node">The node.</param>
		internal virtual void RemoveNode( ExplorerNode node )
		{
			m_explorerTree.RemoveNode( node );
		}

		/// <summary>
		/// Removes all the children from this node.
		/// </summary>
		/// <param name="node">The parent node, if null then remove all children at the root node.</param>
		internal virtual void RemoveNodeChildren( ExplorerNode node )
		{
			m_explorerTree.RemoveNodeChildren( node );
		}

		/// <summary>
		/// Initializes the control.  This method is call in the constructor after the InitializeComponent()
		/// to initialize the control with it's default values.  Derived classes should override this method
		/// to initialize the control with custom options.
		/// </summary>
		protected virtual void InitializeControl()
		{
			SetExplorerTree( new FormsExplorerTree() );
			SetExplorerList( new FormsExplorerList() );
		}

		/// <summary>
		/// Sets the explorer tree.
		/// </summary>
		/// <param name="explorerTree">The explorer tree.</param>
		protected void SetExplorerTree( IExplorerTree explorerTree )
		{
			if( m_explorerTree != null )
			{
				SplitExplorerView.Panel1.Controls.Remove( (Control) m_explorerTree );
				m_explorerTree = null;
			}

			m_explorerTree = explorerTree;

			if( m_explorerTree != null )
			{
				SplitExplorerView.Panel1.Controls.Add( (Control) m_explorerTree );
				( (Control) m_explorerTree ).Dock = DockStyle.Fill;

				// Bind to events
				m_explorerTree.AfterSelect += new EventHandler<ExplorerEventArgs>( ExplorerTree_AfterSelect );
			}
		}

		/// <summary>
		/// Sets the explorer list.
		/// </summary>
		/// <param name="explorerList">The explorer list.</param>
		protected void SetExplorerList( IExplorerList explorerList )
		{
			if( m_explorerList != null )
			{
				SplitExplorerView.Panel2.Controls.Remove( (Control) m_explorerList );
				m_explorerList = null;
			}

			m_explorerList = explorerList;

			if( m_explorerList != null )
			{
				SplitExplorerView.Panel2.Controls.Add( (Control) m_explorerList );
				( (Control) m_explorerList ).Dock = DockStyle.Fill;
			}
		}

		/// <summary>
		/// Handles the AfterSelect event of the ExplorerTree control.
		/// </summary>
		/// <param name="sender">The source of the event.</param>
		/// <param name="args">The <see cref="Pegasus.Windows.Forms.Explorer.ExplorerEventArgs"/> instance containing the event data.</param>
		private void ExplorerTree_AfterSelect( object sender, ExplorerEventArgs args )
		{
			ExplorerNode node = args.Node;
			if( !node.ChildrenLoadded )
			{
				node.LoadChildNodes();
			}

			m_explorerList.SetNodes( node.Nodes );
		}

		/// <summary>
		/// Handles the OnNodeAdded event of the ChildNodes control.
		/// </summary>
		/// <param name="sender">The source of the event.</param>
		/// <param name="args">The <see cref="Pegasus.Windows.Forms.Explorer.ExplorerEventArgs"/> instance containing the event data.</param>
		private void ChildNodes_OnNodeAdded( object sender, ExplorerEventArgs args )
		{
			args.Node.ExplorerView = this;
			AddNode( args.Node );
		}

		/// <summary>
		/// Handles the OnNodeRemoved event of the ChildNodes control.
		/// </summary>
		/// <param name="sender">The source of the event.</param>
		/// <param name="args">The <see cref="Pegasus.Windows.Forms.Explorer.ExplorerEventArgs"/> instance containing the event data.</param>
		private void ChildNodes_OnNodeRemoved( object sender, ExplorerEventArgs args )
		{
			args.Node.ExplorerView = null;
			RemoveNode( args.Node );
		}

		/// <summary>
		/// Handles the OnCollectionClearing event of the ChildNodes control.
		/// </summary>
		/// <param name="sender">The source of the event.</param>
		/// <param name="args">The <see cref="System.EventArgs"/> instance containing the event data.</param>
		private void ChildNodes_OnCollectionClearing( object sender, EventArgs args )
		{
			// Clear all the child view settings
			foreach( ExplorerNode node in m_childNodes )
			{
				node.ExplorerView = null;
			}
		}

		/// <summary>
		/// Handles the OnCollectionCleared event of the ChildNodes control.
		/// </summary>
		/// <param name="sender">The source of the event.</param>
		/// <param name="args">The <see cref="System.EventArgs"/> instance containing the event data.</param>
		private void ChildNodes_OnCollectionCleared( object sender, EventArgs args )
		{
			RemoveNodeChildren( null );
		}
	}
}
